/*
 * 文件名：chess.cpp
 * 功能描述：国际象棋规则和移动验证
 */

#include "chess.h"

const float GRID_SIZE = 300.0 / 8.0;
// 初始化棋盘状态
std::map<std::string, Piece> initializeBoard()
{
    std::map<std::string, Piece> board;

    // 初始化黑色棋子
    board["a8"] = Piece(ROOK, Black);
    board["b8"] = Piece(KNIGHT, Black);
    board["c8"] = Piece(BISHOP, Black);
    board["d8"] = Piece(QUEEN, Black);
    board["e8"] = Piece(KING, Black);
    board["f8"] = Piece(BISHOP, Black);
    board["g8"] = Piece(KNIGHT, Black);
    board["h8"] = Piece(ROOK, Black);

    for (char file = 'a'; file <= 'h'; ++file)
    {
        board[std::string(1, file) + "7"] = Piece(PAWN, Black);
    }

    // 初始化白色棋子
    board["a1"] = Piece(ROOK, White);
    board["b1"] = Piece(KNIGHT, White);
    board["c1"] = Piece(BISHOP, White);
    board["d1"] = Piece(QUEEN, White);
    board["e1"] = Piece(KING, White);
    board["f1"] = Piece(BISHOP, White);
    board["g1"] = Piece(KNIGHT, White);
    board["h1"] = Piece(ROOK, White);

    for (char file = 'a'; file <= 'h'; ++file)
    {
        board[std::string(1, file) + "2"] = Piece(PAWN, White);
    }

    // 初始化空格子
    for (char rank = '3'; rank <= '6'; ++rank)
    {
        for (char file = 'a'; file <= 'h'; ++file)
        {
            board[std::string(1, file) + rank] = Piece(Empty, None);
        }
    }

    return board;
}

// 打印棋盘状态
void printBoard(const std::map<std::string, Piece> &board)
{
    for (char rank = '8'; rank >= '1'; --rank)
    {
        for (char file = 'a'; file <= 'h'; ++file)
        {
            std::string position = std::string(1, file) + rank;
            Piece piece = board.at(position);
            char pieceChar = '.';

            switch (piece.type)
            {
                case KING:
                    pieceChar = (piece.color == White) ? 'K' : 'k';
                    break;
                case QUEEN:
                    pieceChar = (piece.color == White) ? 'Q' : 'q';
                    break;
                case ROOK:
                    pieceChar = (piece.color == White) ? 'R' : 'r';
                    break;
                case BISHOP:
                    pieceChar = (piece.color == White) ? 'B' : 'b';
                    break;
                case KNIGHT:
                    pieceChar = (piece.color == White) ? 'N' : 'n';
                    break;
                case PAWN:
                    pieceChar = (piece.color == White) ? 'P' : 'p';
                    break;
                case Empty:
                    pieceChar = '.';
                    break;
            }

            std::cout << pieceChar << " ";
        }
        std::cout << std::endl;
    }
}

std::pair<int, int> positionToIndex(String position)
{
    int col = position[0] - 'a';
    int row = position[1] - '1';
    return std::make_pair(row, col);
}

std::pair<float, float> indexToCoordinates(std::pair<int, int> index)
{
    float x = (index.second + 0.5) * GRID_SIZE;
    float y = (index.first + 0.5) * GRID_SIZE;
    return std::make_pair(x, y);
}

//void moveChessPiece(String start, String end)
//{
//    std::pair<int, int> startIndex = positionToIndex(start);
//    std::pair<int, int> endIndex = positionToIndex(end);
//
//    std::pair<float, float> startCoord = indexToCoordinates(startIndex);
//    std::pair<float, float> endCoord = indexToCoordinates(endIndex);
//
//    float temp_x_start = startCoord.first;
//    float temp_y_start = startCoord.second;
//    float temp_x_end = endCoord.first;
//    float temp_y_end = endCoord.second;
//
//    Serial.print("Start Coordinates: ");
//    Serial.print(temp_x_start);
//    Serial.print(", ");
//    Serial.println(temp_y_start);
//
//    Serial.print("End Coordinates: ");
//    Serial.print(temp_x_end);
//    Serial.print(", ");
//    Serial.println(temp_y_end);
//
//    // 真实棋子移动
////    moveTo(temp_x_start, temp_y_start);
////    delay(1000);
////    yield();
////    turnOnMagnet();
//
//    float position_x1 = 0.0;
//    float position_y1 = 0.0;
//    float position_x2 = 0.0;
//    float position_y2 = 0.0;
//
//    Serial.println("Finished moveArmTo3");
//    if (temp_x_end > temp_x_start)
//    {
//        position_x1 = temp_x_start + 0.5 * GRID_SIZE;
//        position_x2 = temp_x_end - 0.5 * GRID_SIZE;
//    }
//    else if (temp_x_end < temp_x_start)
//    {
//        position_x1 = temp_x_start - 0.5 * GRID_SIZE;
//        position_x2 = temp_x_end + 0.5 * GRID_SIZE;
//    }
//    else
//    {
//        position_x1 = temp_x_start + 0.5 * GRID_SIZE;
//        position_x2 = temp_x_end + 0.5 * GRID_SIZE;
//    }
//
//    if (temp_y_end > temp_y_start)
//    {
//        position_y1 = temp_y_start + 0.5 * GRID_SIZE;
//        position_y2 = temp_y_end - 0.5 * GRID_SIZE;
//    }
//    else if (temp_y_end < temp_y_start)
//    {
//        position_y1 = temp_y_start - 0.5 * GRID_SIZE;
//        position_y2 = temp_y_end + 0.5 * GRID_SIZE;
//    }
//    else
//    {
//        position_y1 = temp_y_start + 0.5 * GRID_SIZE;
//        position_y2 = temp_y_end + 0.5 * GRID_SIZE;
//    }
//
//    // special case
//    if ((temp_x_end == temp_x_start && abs(temp_y_end - temp_y_start) == GRID_SIZE) ||
//        (temp_y_end == temp_y_start && abs(temp_x_end - temp_x_start) == GRID_SIZE))
//    {
//        moveTo(temp_x_end, temp_y_end);
//    }
//    else
//    {
//        Serial.print("moveArmTo ");
//        Serial.print(position_x1);
//        Serial.print(", ");
//        Serial.println(position_y1);
//        moveTo(position_x1, position_y1);
//        yield();
//
//        Serial.print("moveArmTo ");
//        Serial.print(position_x2);
//        Serial.print(", ");
//        Serial.println(position_y2);
//        moveTo(position_x2, position_y1);
//        yield();
//        moveTo(position_x2, position_y2);
//        yield();
//
//        Serial.print("moveArmTo");
//        Serial.print(position_x1);
//        Serial.print(", ");
//        Serial.println(position_y1);
//        moveTo(temp_x_end, temp_y_end);
//        yield();
//    }
//
//    Serial.println("Finished move");
//    delay(1000);
//    turnOffMagnet();
//    yield();
//
//    // 放下棋子
//    // 控制Z轴下降
//}





#include <stdio.h>
#include <stdbool.h>


// 判断兵的移动是否合法
bool isPawnMoveValid(int startRow, int startCol, int endRow, int endCol, bool isWhite) {
    int rowDiff = endRow - startRow;
    int colDiff = endCol - startCol;
    if (isWhite) {
        // 白兵向前走一格
        if (colDiff == 0 && rowDiff == 1) return true;
        // 白兵第一次可以走两格
        if (colDiff == 0 && startRow == 1 && rowDiff == 2) return true;
        // 白兵吃子斜走一格
        if (colDiff == 1 || colDiff == -1 && rowDiff == 1) return true;
    } else {
        // 黑兵向前走一格
        if (colDiff == 0 && rowDiff == -1) return true;
        // 黑兵第一次可以走两格
        if (colDiff == 0 && startRow == 6 && rowDiff == -2) return true;
        // 黑兵吃子斜走一格
        if (colDiff == 1 || colDiff == -1 && rowDiff == -1) return true;
    }
    return false;
}

// 判断马的移动是否合法
bool isKnightMoveValid(int startRow, int startCol, int endRow, int endCol) {
    int rowDiff = abs(endRow - startRow);
    int colDiff = abs(endCol - startCol);
    return (rowDiff == 2 && colDiff == 1) || (rowDiff == 1 && colDiff == 2);
}

// 判断象的移动是否合法
bool isBishopMoveValid(int startRow, int startCol, int endRow, int endCol) {
    int rowDiff = abs(endRow - startRow);
    int colDiff = abs(endCol - startCol);
    return rowDiff == colDiff;
}

// 判断车的移动是否合法
bool isRookMoveValid(int startRow, int startCol, int endRow, int endCol) {
    return (startRow == endRow) || (startCol == endCol);
}

// 判断后（皇后）的移动是否合法
bool isQueenMoveValid(int startRow, int startCol, int endRow, int endCol) {
    return isBishopMoveValid(startRow, startCol, endRow, endCol) || isRookMoveValid(startRow, startCol, endRow, endCol);
}

// 判断王的移动是否合法
bool isKingMoveValid(int startRow, int startCol, int endRow, int endCol) {
    int rowDiff = abs(endRow - startRow);
    int colDiff = abs(endCol - startCol);
    return (rowDiff <= 1 && colDiff <= 1);
}

// 判断棋子移动是否合法的通用函数
bool isMoveValid(int startRow, int startCol, int endRow, int endCol, PieceType piece) {
    switch (piece) {
        case PAWN:
            return isPawnMoveValid(startRow, startCol, endRow, endCol, startRow < 5);
        case KNIGHT:
            return isKnightMoveValid(startRow, startCol, endRow, endCol);
        case BISHOP:
            return isBishopMoveValid(startRow, startCol, endRow, endCol);
        case ROOK:
            return isRookMoveValid(startRow, startCol, endRow, endCol);
        case QUEEN:
            return isQueenMoveValid(startRow, startCol, endRow, endCol);
        case KING:
            return isKingMoveValid(startRow, startCol, endRow, endCol);
        default:
            return false;
    }
}



#include <iostream>
#include <sstream>
#include <vector>

std::string ChessUtils::convertToChessPosition(int row, int col) {
    char file = 'a' + col;
    char rank = '1' + (7 - row);
    return std::string(1, file) + std::string(1, rank);
}

void ChessUtils::updateBoard(std::string& board, const std::string& move) {
    std::string startPosition = move.substr(0, 2);
    std::string endPosition = move.substr(2, 2);
    int startRow, startCol, endRow, endCol;
    for (int row = 0; row < 8; row++) {
        for (int col = 0; col < 8; col++) {
            std::string position = convertToChessPosition(row, col);
            if (position == startPosition) {
                startRow = row;
                startCol = col;
            }
            if (position == endPosition) {
                endRow = row;
                endCol = col;
            }
        }
    }
    char temp = board[endRow * 8 + endCol];
    board[endRow * 8 + endCol] = board[startRow * 8 + startCol];
    board[startRow * 8 + startCol] = temp;
}

std::string ChessUtils::generateFENFromUCI(const std::string& initialFEN, const std::string& moves) {
    std::string fen = initialFEN;
    std::istringstream iss(moves);
    std::string move;
    while (iss >> move) {
        updateBoard(fen, move);
    }
    return fen;
}